package edu.uic.cs.cs582.process.impl;

import edu.uic.cs.cs582.data.Component;
import edu.uic.cs.cs582.misc.Assert;

/**
 * Please co-reference {@link AbstractBasicVariablesGeneratorImpl}
 * @author Hong Wang
 *
 */
public class SatIndexParser
{
	public static final int SAT_VARIABLE_SUFFIX_POSITIVE = 1;
	public static final int SAT_VARIABLE_SUFFIX_NEGATIVE = 2;
	public static final int SAT_VARIABLE_SUFFIX_FREQUENCY_DIGIT = 3;

	public static final int SAT_VARIABLE_SUFFIX_LENGTH = 2;

	public static interface Index
	{
	}

	public static class SynsetIndex implements Index
	{
		private int synsetIndex = -1;

		public SynsetIndex(int synsetIndex)
		{
			this.synsetIndex = synsetIndex;
		}

		public int getSynsetIndex()
		{
			return synsetIndex;
		}

	}

	public static class WordIndex implements Index
	{
		private int wordIndexInOneComponent = -1;

		//		private int variableIndex = -1;

		public WordIndex(int wordIndexInOneComponent, int variableIndex)
		{
			this.wordIndexInOneComponent = wordIndexInOneComponent;
			//			this.variableIndex = variableIndex;
		}

		public int getWordIndexInOneComponent()
		{
			return wordIndexInOneComponent;
		}

		//		public int getVariableIndex()
		//		{
		//			return variableIndex;
		//		}

		public String toString()
		{
			return "WordIndex - " /*+ variableIndex + "("
									+ Integer.toBinaryString(variableIndex) + "):"*/
					+ wordIndexInOneComponent + "("
					+ Integer.toBinaryString(wordIndexInOneComponent)
					/*+ "):" + synsetIndexInOneWord + "("
					+ Integer.toBinaryString(synsetIndexInOneWord) */+ ")";
		}
	}

	/*public static class SynsetAndWordIndex implements Index
	{
		private int synsetIndex = -1;
		private int wordIndexInOneComponent = -1;

		public SynsetAndWordIndex(int synsetIndex, int wordIndexInOneComponent)
		{
			this.synsetIndex = synsetIndex;
			this.wordIndexInOneComponent = wordIndexInOneComponent;
		}

		public int getSynsetIndex()
		{
			return synsetIndex;
		}

		public int getWordIndexInOneComponent()
		{
			return wordIndexInOneComponent;
		}

	}*/

	public static Index parseIndex(int indexReturnedBySat, Component component)
	{
		indexReturnedBySat = Math.abs(indexReturnedBySat);
		if (indexReturnedBySat % 4 == SAT_VARIABLE_SUFFIX_POSITIVE
				|| indexReturnedBySat % 4 == SAT_VARIABLE_SUFFIX_NEGATIVE)
		{
			return parseSynsetIndex(indexReturnedBySat);
		}

		if (indexReturnedBySat % 4 == SAT_VARIABLE_SUFFIX_FREQUENCY_DIGIT)
		{
			return parseWordIndex(indexReturnedBySat, component);
		}

		Assert.isTrue(false, "Index must end with ["
				+ SAT_VARIABLE_SUFFIX_POSITIVE + "|"
				+ SAT_VARIABLE_SUFFIX_NEGATIVE + "|"
				+ SAT_VARIABLE_SUFFIX_FREQUENCY_DIGIT + "]. ");
		return null;
	}

	private static SynsetIndex parseSynsetIndex(int indexReturnedBySat)
	{
		return new SynsetIndex(indexReturnedBySat >> SAT_VARIABLE_SUFFIX_LENGTH);
	}

	private static WordIndex parseWordIndex(int indexReturnedBySat,
			Component component)
	{
		indexReturnedBySat = indexReturnedBySat >> SAT_VARIABLE_SUFFIX_LENGTH;

		int wordIndexBinaryLength = component.getWordsNumberBinaryLength();
		int mask = (1 << wordIndexBinaryLength) - 1;
		int wordIndexInOneComponent = indexReturnedBySat & mask;
		int variableIndex = indexReturnedBySat >> wordIndexBinaryLength;

		return new WordIndex(wordIndexInOneComponent, variableIndex);
	}

	/*private staticWordIndexSynsetIndex parseWordIndex(
			int indexReturnedBySat, Component component)
	{
		//		indexReturnedBySat = indexReturnedBySat >> SAT_VARIABLE_SUFFIX_LENGTH;
		//
		//		int wordIndexBinaryLength = component.getWordsNumberBinaryLength();
		//		int mask = (1 << wordIndexBinaryLength) - 1;
		//		int wordIndexInOneComponent = indexReturnedBySat & mask;
		//
		//		int variableIndex = indexReturnedBySat >> wordIndexBinaryLength;

		Integer synsetIndex = component
				.getSynsetIndexByFrequencySymbol(indexReturnedBySat);
		Assert.notNull(synsetIndex);
		return new SynsetIndex(synsetIndex);

		//		return new WordIndex(wordIndexInOneComponent, variableIndex);

	}*/

}
